//
// Created by zhouwd on 2019/6/27.
//

#include "encode.h"

static uint64_t getCurrentTime()      //直接调用这个函数就行了，返回值最好是int64_t，long long应该也可以
{
    struct timeval tv;
    gettimeofday(&tv,NULL);    //该函数在sys/time.h头文件中
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

int _ENCODE::init(const char *dst_file_path) {

    this->dst_file_path = dst_file_path;

    codec = AMediaCodec_createEncoderByType("video/avc");

    if (codec == NULL) {
        return -1;
    }

    AMediaFormat *format = AMediaFormat_new();

    AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, "video/avc");
    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, 2500000);
    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, 30);
    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, 720); // 视频宽度
    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, 1280); // 视频高度
    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, 21);
    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, 1);

    presentationTimeUs = getCurrentTime();

    media_status_t rc = AMediaCodec_configure(codec, format, NULL, NULL, AMEDIACODEC_CONFIGURE_FLAG_ENCODE);

    if (rc != AMEDIA_OK ) {

        AMediaCodec_delete(codec);

        return rc;
    }

    return 0;
}




int _ENCODE::inputEncodeBuffer(char *data, size_t buf_size) {

    if (!status) {
        ALOGE("inputEncodeBuffer >>>>");
        return -1;
    }

    ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, -1);
    ALOGE("inputEncodeBuffer >>>> %d", bufidx);
    if (bufidx >= 0) {
        // 获取buffer的索引
        size_t out_size;

        uint8_t *inputBuf = AMediaCodec_getInputBuffer(codec, bufidx, &out_size);
        if (inputBuf != nullptr && buf_size <= out_size) {
            // 将待解码的数据copy到硬件中
            memcpy(inputBuf, data, buf_size);

            uint64_t pts = getCurrentTime() - presentationTimeUs;

            media_status_t status = AMediaCodec_queueInputBuffer(codec, bufidx, 0, buf_size, pts,0);
            ALOGE("status >>>> %d >>pts >> %d", status, pts);
        }
    }

    AMediaCodecBufferInfo bufferInfo;

    ssize_t bufidx1 = AMediaCodec_dequeueOutputBuffer(codec, &bufferInfo, 0);
    ALOGE("AMediaCodec_dequeueOutputBuffer >>>>> %d", bufidx1);
    if (bufidx1 >= 0) {
        size_t outsize;

        uint8_t* outputBuf = AMediaCodec_getOutputBuffer(codec, bufidx1, &outsize);
        ALOGE("AMediaCodec_dequeueOutputBuffer >> outsize >> %d", bufferInfo.size);
        if (outputBuf != nullptr) {
            ALOGE("AMediaCodec_dequeueOutputBuffer1111");
        }

        AMediaCodec_releaseOutputBuffer(codec, bufidx1, bufferInfo.size != 0);

    } else {
        switch (bufidx1) {
            // 解码输出的格式发生变化
            case AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED:
                ALOGE("AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED");
                break;
            case AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED:
                ALOGE("AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED");
                break;
            default:
                ALOGE("AMediaCodec_dequeueOutputBuffer > default");
                break;
        }
    }

    return 0;
}

int _ENCODE::startEncode() {
    ALOGE("startEncode");
    status = true;
    AMediaCodec_start(codec);
    //开启线程
    //start();

    return 0;
}

int _ENCODE::stopEncode() {
    status = false;
    ALOGE("stopEncode");
    return 0;
}


void _ENCODE::run() {
    ALOGE("outputEncodeBuffer1111");

    while (status) {
        AMediaCodecBufferInfo bufferInfo;
        ssize_t bufidx = AMediaCodec_dequeueOutputBuffer(codec, &bufferInfo, 2000);
        ALOGE("AMediaCodec_dequeueOutputBuffer >>>>> %d", bufidx);
        if (bufidx >= 0) {
            size_t outsize;
            uint8_t* outputBuf = AMediaCodec_getOutputBuffer(codec, bufidx, &outsize);
            ALOGE("AMediaCodec_dequeueOutputBuffer");
            if (outputBuf != nullptr) {
                ALOGE("AMediaCodec_dequeueOutputBuffer1111");
            }
        } else {
            switch (bufidx) {
                // 解码输出的格式发生变化
                case AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED:
                    ALOGE("AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED");
                    break;
                case AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED:
                    ALOGE("AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED");
                    break;
                default:
                    ALOGE("AMediaCodec_dequeueOutputBuffer > default");
                    break;
            }
        }
    }


}

